package de.realriot.ipsdroid.v1.beta;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import de.realriot.libs.ipsjson.IPSException;
import de.realriot.libs.ipsjson.IPSjson;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.sqlite.SQLiteException;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.TextView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupClickListener;

public class IPScontent extends Activity {
	
	// Select 1 - Trigger a variable value-refresh.
	protected static final int CONTEXTMENU_IPS_REFRESH = 2;
	
	// Initialize the DataHelper and DataCache.
	private IPSDataHelper dh = null;
	private IPSDataCache dc = null;

	// Get arguments for this activity.
	private Bundle activitiyArguments = null;
	
	// Variables for the layout.
	private ExpandableListView ipsobjListLV;
	private IPSExRowAdapter ipsobjListLvAdapter;
	private ProgressDialog progressDialog;
	
	private IPSListViewData ipslv;
	private TextView statusTV;

	// Data connection variables.
	private IPSjson ipshost;
	private Thread dataThread;
	private Thread valueThread;
	
	// Thread flags.
	private Boolean vRefresherRunning;
	private Boolean vRefresher;
	
	// Create a method to sort JSONObjects.
	public static Comparator<JSONObject> TIPSObjectSort = new Comparator<JSONObject>() {
		public int compare(JSONObject obj1, JSONObject obj2)
		{
			String e1 = "";
			String e2 = "";
			try {
				e1 = obj1.getString("ObjectName");
				e2 = obj2.getString("ObjectName");
			} catch (JSONException e) {}

			return e1.compareTo(e2);
		}
	};

    /** Called when the activity is first created. */
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.ipscontent);
        
        // Handle arguments for this activity.
        activitiyArguments = getIntent().getExtras();

        // Initialize DataHelper for database access.
        dh = new IPSDataHelper(this, activitiyArguments.getString("host"));
        
        // Init layout elements.
        myInitControls();
        
        // Fetch connection informations about the ip-symcon server.
        Hashtable<String,String> hostEntry = null;
        try 
        {
        	hostEntry = dh.getHostFromDB(activitiyArguments.getString("host"));
        
        	// Create http-connection and fetch informations from ipsserver.
			ipshost = new IPSjson(hostEntry.get("host"), 
					hostEntry.get("port"), 
					hostEntry.get("username"),
					hostEntry.get("password"),
					Boolean.parseBoolean(hostEntry.get("ssl")));
        } catch (SQLiteException e)
        {
        	showMessageBox("2", "SQL " + getString(R.string.str_error),
				e.getMessage());
        	return;
		} catch (IPSException e) {
			showMessageBox("2", getString(R.string.str_error), e.getMessage());
			return;
		}

		// After initializing the database and JSON connection, we can init the cachingObject.
		dc = new IPSDataCache(dh, ipshost, messageHandler);
		
		// Create the listView.
		createIPSListView(activitiyArguments.getString("showlevel"), messageHandler);
		ipslvValueWatcher();
    }
	
    /** Called when the activity is paused. */
    public void onStop() {
		super.onStop();

		// Stop the valueRefresh thread.
		vRefresherRunning = false;
	}

    /** Called when the activity is resumed. */
    public void onRestart() {
		super.onRestart();
		
		// Restart the valueRefresh thread.
		if (! valueThread.isAlive() )
		{
			valueThread = new Thread(valueThread);
			valueThread.start();
		}
	}

    /** Called when the activity is destroyed. */
    public void onDestroy() {
		super.onDestroy();

		vRefresherRunning = false;
	}
    
	/**
     * - Initialize layout controls.
     * - set adapter for listviews.
     * - connect these adapters to the listviews.
     * - set layout parameters.
     */
    private void myInitControls()
    {
    	// Find layout ids.
    	ipsobjListLV = (ExpandableListView)findViewById(R.id.ipsobjListLV);
    	statusTV = (TextView)findViewById(R.id.statusTV);
    	
        // Create onGroupClick listener for the ipsobjListLV.
        ipsobjListLV.setOnGroupClickListener(new OnGroupClickListener() {
			@Override
			public boolean onGroupClick(ExpandableListView parent, View v,
					int groupPosition, long id) {
				try {
					JSONObject obj = ipsobjListLvAdapter.getGroup(groupPosition);
					
					// Group is an: INSTANCE.
					if ( obj.get("ObjectType").equals(IPSObjectType.otCategory) )
					{
						// Only start new intent, if a network connection is established and
						// ready for use.
						if ( isNetworkAvailable() )
						{
							Intent myIntent = new Intent();
			        		myIntent.setClass(IPScontent.this, IPScontent.class);
			        		myIntent.putExtra("showlevel", obj.getString("ObjectID"));
			        		myIntent.putExtra("host", activitiyArguments.getString("host"));
			        		startActivity(myIntent);
		        		} else
		        			showMessageBox("0", getString(R.string.error_network_error),
		        					getString(R.string.error_network_not_ready));
					}
					
					// Group is a: SCRIPT.
					if ( ipsobjListLvAdapter.getGroup(groupPosition).get("ObjectType").equals(IPSObjectType.otScript) )
						showMessageBox("1", "Script-Auswahl", "TODO: Script :-)");
					
					// Group is a: VARIABLE.
					if ( ipsobjListLvAdapter.getGroup(groupPosition).get("ObjectType").equals(IPSObjectType.otVariable) )
						showMessageBox("1", "Variablen-Auswahl", "TODO: Variable :-)");
				} catch (JSONException e) {
					showMessageBox("0", getString(R.string.str_error),
							e.getMessage());
				}
				return false;
			}
        });
        
        // Create onChildClick listener for the ipsobjListLV.
        ipsobjListLV.setOnChildClickListener(new OnChildClickListener() {
			@Override
			public boolean onChildClick(ExpandableListView parent, View v,
					int groupPosition, int childPosition, long id) {
				try {
					// Child is a: SCRIPT.
					if ( ipsobjListLvAdapter.getChild(groupPosition, childPosition).get("ObjectType").equals(IPSObjectType.otScript) )
						showMessageBox("1", "Script-Auswahl", "TODO: Script :-)");
					
					// Child is a: VARIABLE.
					if ( ipsobjListLvAdapter.getChild(groupPosition, childPosition).get("ObjectType").equals(IPSObjectType.otVariable) )
						showMessageBox("1", "Variablen-Auswahl", "TODO: Variable :-)");
				} catch (JSONException e) {
					showMessageBox("0", getString(R.string.str_error), e.getMessage());
				}
				return false;
			}
        });
    }

	/**
	 * Creates the OptionsMenu with defined menu entries.
	 */
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(0, CONTEXTMENU_IPS_REFRESH, 0, getString(R.string.text_refresh_values));
        return true;
    }

	/**
	 * Handles the selected items of the OptionsMenu.
	 */
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        
        // Trigger a value-refresh within the listview.
        case CONTEXTMENU_IPS_REFRESH:
        	ipsobjListLvAdapter.emptyValueCache();
        	ipsobjListLvAdapter.notifyDataSetChanged();
        	vRefresher = true;
        	
        	// Start valueThread if it is inactive.
        	if (! valueThread.isAlive() )
        	{
        		// Restart valueThread.
        		valueThread = new Thread(valueThread);
        		valueThread.start();
        	}
        	return true;
        }
        return false;
    }
    
	/**
     * This is the main-function which is called to build a listview.
     * It calls all other functions which are needed to get informations
     * from the ips-server or the cache. This method will create a thread,
     * so the interaction within the activity will be still possible.
     * 
     * @param ipssoap The ipssoap-Object which is used to fetch informations from the server.
     * @param parentID This is the ID of the parent Object.
     * @param messageHandler messageHandler to return values from the created thread.
     */
    public void createIPSListView(final String parentID, final Handler messageHandler)
    {
        progressDialog = new ProgressDialog(this);
   		progressDialog.setTitle(getString(R.string.text_please_wait));
        progressDialog.setMessage(getString(R.string.str_loading) + "...\n");
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog.setMax(0);
        progressDialog.setProgress(0);
   		progressDialog.setCancelable(false);
   		progressDialog.show();
   		
   		dataThread = new Thread()
        {
            public void run()
            {
            	ipslv = new IPSListViewData();

            	JSONArray objList = new JSONArray();
            	try {
            		// Get initial objectlist.
					objList = dc.IPS_GetObjectChilds(Integer.parseInt(parentID));
				} catch (SQLiteException e) {
					showMessageBoxByHandler("2", "SQL " + getString(R.string.str_error), e.getMessage());
					messageHandler.sendEmptyMessage(0);
            	} catch (JSONException e) {
					showMessageBoxByHandler("2", getString(R.string.str_error), e.getMessage());
					messageHandler.sendEmptyMessage(0);
				} catch (IPSException e) {
					showMessageBoxByHandler("2", getString(R.string.str_error), e.getMessage());
					messageHandler.sendEmptyMessage(0);
				}
            	
				// If we got a list with entries, we can go on and work with these objects.
            	if ( objList.length() > 0 )
            	{
            		try {
						ipslv = createListViewDataObject(objList);
					} catch (JSONException e) {
						showMessageBoxByHandler("2", getString(R.string.str_error), e.getMessage());
						messageHandler.sendEmptyMessage(0);
					} catch (IPSException e) {
						showMessageBoxByHandler("2", getString(R.string.str_error), e.getMessage());
						messageHandler.sendEmptyMessage(0);
					}
            		ipsobjListLvAdapter = new IPSExRowAdapter(IPScontent.this, ipslv);
            		messageHandler.sendEmptyMessage(0);
            	} else
            	{
            		// We got a reply with NO childs. Just finish this thread.
            		messageHandler.sendEmptyMessage(0);
            	}
            }
        };
        dataThread.start();
    }

	/**
     * This method creates a listViewDataObject which holds all needed informations
     * to work with. It's also called a dataHolder.
     * 
     * @param list A list of objects. This list is used to fetch all other informations.
     * @return The created dataHolder-Object.
	 * @throws JSONException 
	 * @throws IPSException 
     */
	public IPSListViewData createListViewDataObject(JSONArray objList) throws JSONException, IPSException
	{
		IPSListViewData ipsLV = new IPSListViewData();

		// Loop objects to find objectType.
		for ( int i = 0; i < objList.length(); i++ )
		{
			JSONObject obj = objList.getJSONObject(i);
			JSONObject lnObj;
			
			// Update progress dialog.
			updateProgressDialog(obj.getString("ObjectName"), 1, 1);
			
			// Skip hidden objects.
			if ( obj.getBoolean("ObjectIsHidden") == true )
				continue;
			
			// Handle links.
			if ( obj.get("ObjectType").equals(IPSObjectType.otLink) )
			{
				lnObj = dc.fetchCorrObject(obj);

				lnObj.put("ParentID", obj.get("ParentID"));
				lnObj.put("ObjectName", obj.get("ObjectName"));
				obj = lnObj;
			}
			
			// Find all categories.
			if ( obj.get("ObjectType").equals(IPSObjectType.otCategory) )
				ipsLV.catObjList.add(obj);

			if ( obj.get("ObjectType").equals(IPSObjectType.otInstance) )
			{
				JSONObject insObj = (JSONObject) dc.fetchCorrObject(obj).get("ModuleInfo");
				
				// Only add instance if it's a DummyModule or Device.
				if ( insObj.get("ModuleType").equals(3) )
				{
					ipsLV.insObjList.add(obj);
				
					// This is an instance. We have to check if it has childs.
					// Save them to an ArrayList.
					JSONArray tmpObjList = dc.IPS_GetObjectChilds(Integer.parseInt(obj.getString("ObjectID")));
					
					for ( int j = 0; j < tmpObjList.length(); j++ )
					{
						JSONObject tmpObj = tmpObjList.getJSONObject(j);
	
						// Handle links.
						if ( tmpObj.get("ObjectType").equals(IPSObjectType.otLink) )
						{
							lnObj = dc.fetchCorrObject(tmpObj);

							lnObj.put("ParentID", tmpObj.get("ParentID"));
							lnObj.put("ObjectName", tmpObj.get("ObjectName"));

							ipsLV.insChildObjList.add(lnObj);
						} else
						{
							ipsLV.insChildObjList.add(tmpObj);
						}
					}
				}
			}

			// Find all variables.
			if ( obj.get("ObjectType").equals(IPSObjectType.otVariable) )
				ipsLV.varObjList.add(obj);

			// Find all scripts.
			if ( obj.get("ObjectType").equals(IPSObjectType.otScript) )
				ipsLV.scrObjList.add(obj);
		}
		
		// Fetch variables for objects.
		ipsLV.varList = fetchVariables(ipsLV.varObjList, ipsLV.varList);
		ipsLV.varList = fetchVariables(ipsLV.insChildObjList, ipsLV.varList);

		// Fetch profiles for variables.
		ipsLV.varProfileList = fetchVarProfiles(ipsLV.varList, ipsLV.varProfileList);
		
		// Sort the collected informations.
		Collections.sort(ipsLV.catObjList, TIPSObjectSort);
		Collections.sort(ipsLV.insObjList, TIPSObjectSort);
		Collections.sort(ipsLV.varObjList, TIPSObjectSort);
		Collections.sort(ipsLV.scrObjList, TIPSObjectSort);
		Collections.sort(ipsLV.insChildObjList, TIPSObjectSort);
		
		return ipsLV;
	}

	/**
     * Fetches the variable-Objects out of a given object-List.
     * 
     * @param objList The Object list.
     * @param existingList The existing list of variable-Objects.
     * @param The new created variable-Object list.
	 * @throws JSONException 
	 * @throws IPSException 
     */
	public ArrayList<JSONObject> fetchVariables(ArrayList<JSONObject> objList,
			ArrayList<JSONObject> existingList ) throws JSONException, IPSException
	{
		ArrayList<JSONObject> retArr = new ArrayList<JSONObject>();

		for ( JSONObject obj : objList )
		{
			// Only handle this objects if it's from type variable.
			if ( obj.get("ObjectType").equals(IPSObjectType.otVariable) )
			{
				Boolean found = false;
				for ( JSONObject var : existingList )
					if ( var.get("VariableID").equals(obj.get("ObjectID")) )
						found = true;
				if ( found == false )
				{
					retArr.add(dc.fetchCorrObject(obj));
				}
			}
		}
		if ( retArr.size() > 0 )
			existingList.addAll(retArr);
		return existingList;
	}

	/**
     * Fetches the variableProfiles for a given list of variable-Objects.
     * 
     * @param varList List of variable-Objects.
     * @param existingList Existing list of variableProfiles.
     * @param The new created variableProfile-Object list.
	 * @throws JSONException 
	 * @throws IPSException 
     */
	public ArrayList<JSONObject> fetchVarProfiles(ArrayList<JSONObject> varList,
			ArrayList<JSONObject> existingList ) throws JSONException, IPSException
	{
		ArrayList<JSONObject> retArr = new ArrayList<JSONObject>();
		
		for ( JSONObject var : varList )
		{
			JSONObject varp = dc.IPS_GetVariableProfile(var);
			
			if ( varp != null )
			{
				Boolean found = false;
				for ( JSONObject eleVarp : existingList )
					if ( eleVarp.get("ProfileName").equals(varp.get("ProfileName")) )
						found = true;
				if ( found == false )
					retArr.add(varp);
			}
		}
		if ( retArr.size() > 0 )
			existingList.addAll(retArr);
		return existingList;
	}

	/**
	 * Checks whether the device is able to connect to the network.
	 * 
	 * @return TRUE if a network connection is available, otherwise FALSE.
	 */
	public boolean isNetworkAvailable()
	{
		ConnectivityManager connMgr=(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo netInfo=connMgr.getActiveNetworkInfo();
		
		return( netInfo != null && netInfo.isConnected() );
	}
	
	/**
     * This function creates a loop which always runs. The assignment for this loop
     * is to update all variable values. After updating all values, the threads
     * sleeps for a defined amount of time. Afterwards, it starts again to fetch
     * new values.
     */
	public void ipslvValueWatcher()
	{
		vRefresher = false;
        valueThread = new Thread()
        {
            public void run()
            {
            	vRefresherRunning = true;
            	
            	ArrayList<Hashtable<String, String>> tmpValueCache = new ArrayList<Hashtable<String,String>>();
            	int counter = 0;
            	while ( vRefresherRunning )
            	{
            		// Check if we have to run the update functions or not.
            		if ( counter < 12 && ! vRefresher )
            		{
            			// Sleep just for 2 seconds
						try {
							Thread.sleep(5000);
							counter++;
							
							if ( ipsobjListLvAdapter == null || ! isNetworkAvailable() ||
									( ipslv.varList.size() >= 0 && ipsobjListLvAdapter.getValueCount() > 0 ) )
								continue;
						} catch (InterruptedException e)
						{
							updateStatusTV("");
							showMessageBoxByHandler("0", "Value " + getString(R.string.str_error),
									e.getMessage());
							return;
						}
            		} else
            		{
            			// Normally we have to start the refresher now.
            			counter = 0;
            			vRefresher = false;
            			
                		if ( ipslv.varList.size() == 0 )
                			continue;
            		}
            		
            		// Check for an existing kill request for this thread.
            		if ( ! vRefresherRunning )
            			continue;

            		// Update status TextView.
            		updateStatusTV(getString(R.string.text_updating_values));
            		
            		// Clear the temp dataCache.
            		tmpValueCache.clear();
	            	for ( JSONObject var : ipslv.varList )
	            	{
	        			String result = "";
						try {
							result = ipshost.IPS("GetValueFormatted",
									new Object[] {var.get("VariableID")} ).getString("result");
						} catch (JSONException e) {
							updateStatusTV("");
							showMessageBoxByHandler("0", getString(R.string.str_error),
									e.getMessage());
							return;
						} catch (IPSException e) {
							updateStatusTV("");
							showMessageBoxByHandler("0", getString(R.string.str_error),
									e.getMessage());
							return;
						}
	        			
						// Create hastable which will be added to the valueCache.
	        			Hashtable<String, String> ht = new Hashtable<String, String>();
	        			try {
							ht.put("id", var.getString("VariableID"));
						} catch (JSONException e) {
							updateStatusTV("");
							showMessageBoxByHandler("0", getString(R.string.str_error),
									e.getMessage());
							return;
						}
	        			ht.put("value", result);
	        			tmpValueCache.add(ht);
	            	}
            		if ( ipsobjListLvAdapter != null )
            		{
            			ipsobjListLvAdapter.setDataCache(tmpValueCache);
            			updateStatusTV("");
            			refreshListView();
            		}
	            }
            }
        };
        valueThread.start();
	}
    
	/**
     * Shows an box with a given title and text.
     * The user has to acknowledge these message by
     * clicking the OK button. By given a mode the style
     * of the box will change.
     * - 0 ErrorBox
     * - 1 InfoBox
     * - 2 ErrorBox with request to finish activity.
     * 
     * @param mode The mode of the messageBox
     * @param title Title of the messageBox
     * @param text Text to display 
     */
    public void showMessageBox(String mode, String title, String text)
	{
    	// ERRORBOX. Just a small error. No further action needed.
    	if ( mode.equals("0") )
    	{
    		AlertDialog.Builder msgBox;
    		msgBox = new AlertDialog.Builder(this);
    		
    		msgBox.setIcon(R.drawable.app_problem);
    		msgBox.setTitle(title);
    		msgBox.setMessage(text);
    		msgBox.setPositiveButton("OK", null);

    		msgBox.create();
    		msgBox.show();
    	}
    	
    	// INFOBOX. This just an information box.
    	if ( mode.equals("1") )
    	{
    		AlertDialog.Builder msgBox;
    		msgBox = new AlertDialog.Builder(this);
    		
    		msgBox.setIcon(R.drawable.app_problem);
    		msgBox.setTitle(title);
    		msgBox.setMessage(text);
    		msgBox.setPositiveButton("OK", null);

    		msgBox.create();
    		msgBox.show();
    	}
    	
    	// ERROR with request to finish() activity.
    	if ( mode.equals("2") )
    	{
    		AlertDialog.Builder msgBox;
    		msgBox = new AlertDialog.Builder(this);
    		
    		msgBox.setIcon(R.drawable.app_problem);
    		msgBox.setTitle(title);
    		msgBox.setMessage(text);
    		msgBox.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    finish();
                }
            });

    		msgBox.create();
    		msgBox.show();
    	}
	}
    
	/**
     * Reports a message via a messageHandler.
     * The function showMessageBox() is used to display the dialog.
     * 
     * @param mode The mode of the messageBox
     * @param title Title of the messageBox
     * @param text Text to display 
     */
    private void showMessageBoxByHandler(String mode, String title, String message)
    {
       	Message msg = new Message();
    	
    	// Set reporting type.
    	msg.what = 1;
   
    	// Set some additional informations for errorMessage.
    	Bundle bundle = new Bundle();
    	bundle.putString("mode", mode);
    	bundle.putString("title", title);
    	bundle.putString("message", message);
    	msg.setData(bundle);
    	
    	// Send message.
    	messageHandler.sendMessage(msg);
    }

	/**
     * This method uses the messageHandler to trigger a
     * refresh of the listView.
     */
	public void refreshListView()
	{
    	messageHandler.sendEmptyMessage(3);
	}

	/**
     * This method updates the statusTextView to display
     * current processes and/or user informations.
     * 
     * @param text Text to display within the statusTextView.
     */
	public void updateStatusTV(String text)
	{
    	Bundle data = new Bundle();
    	data.putString("message", text);
    	
    	Message msg = new Message();
    	msg.what = 4;
    	msg.setData(data);
    	
    	messageHandler.sendMessage(msg);
	}
	
	/**
     * This method uses the messageHandler to update the progressDialog.
     * 
     * @param text Text to display within the dialog.
     * @param value The actual value of a progress.
     * @param maxvalue The max value of a progress.
     */
	public void updateProgressDialog(String text, int value, int maxvalue)
	{
    	Bundle data = new Bundle();
    	data.putString("state", text);
    	data.putInt("value", value);
    	data.putInt("maxvalue", maxvalue);
    	
    	Message msg = new Message();
    	msg.what = 2;
    	msg.setData(data);
    	
    	messageHandler.sendMessage(msg);
	}
    
	/**
     * MessageHandler to receive signals from other threads.
     */
    private Handler messageHandler = new Handler()
    {
    	Bundle data = null;
        @Override
        public void handleMessage(Message msg)
        {
        	switch (msg.what)
        	{
	        	// Add the listViewAdapter to the listview.
	        	case 0:
	        		ipsobjListLV.setAdapter(ipsobjListLvAdapter);
	        		ipsobjListLV.setIndicatorBounds(0, 0);
	
	        		progressDialog.hide();
	        		progressDialog.dismiss();
	        		break;
	
	        	// Show the messageBox.
	        	case 1:
	        		data = msg.getData();
	        		
	        		// Only show messageBox if we have a valid dataset.
	        		if ( data.size() > 0 )
	        		{
	        			String title = "";
	        			if (! data.containsKey("title") )
	        				title = getString(R.string.str_error);
	        			else
	        				title = data.getString("title");
	
	        			showMessageBox(data.getString("mode"),
	        					title,
	        					data.getString("message"));
	        		}
	        		break;
	
	        	// Update the progressDialog.
	        	case 2:
	        		data = msg.getData();
	        		
	        		if ( data.size() > 0 )
	        		{
		        		String text = data.getString("state");
		        		
		        		// Change the textlength to a maximum.
		        		if ( text.length() > 25 )
		        			text = text.substring(0, 24) + "...";
		        		if (! text.equals("") )
		        			progressDialog.setMessage(getString(R.string.str_loading) + ":\n" + 
		        					text);
		       			progressDialog.setMax(data.getInt("maxvalue"));
		       			progressDialog.setProgress(data.getInt("value"));
	        		}
	        		break;
	        		
	           	// Refresh the listView.
	        	case 3:
	        		ipsobjListLvAdapter.notifyDataSetChanged();
	        		break;
	        	
	        	// Update the statusTextView.
	        	case 4:
	        		data = msg.getData();
	        		
	        		if ( data.size() > 0 )
	        		{
	        			if ( data.getString("message").equals("") )
	        			{
		        			statusTV.setText(data.getString("message"));
		        			statusTV.setBackgroundColor(Color.TRANSPARENT);
	        			} else
	        			{
		        			statusTV.setText(data.getString("message"));
		        			statusTV.setBackgroundColor(Color.WHITE);
	        			}
	        		}
	        		break;
        	}
        }
    };
}